#include "analisador.h"


int busca_na_lista (char encontrado[30], tipo lista_tipos, char *tipo_var)
{
	type percorre;
	percorre = lista_tipos->prim;
	while(percorre != NULL)
	{
		if(strcmp(encontrado,percorre->id) == 0)
		{
			strcpy(tipo_var,percorre->tipo);
			return 1;
		}
		percorre = percorre->prox;
	}
	return 0;
}


char *limpa_simbolo(char token[100], char nome_var[30])
{
	int i = 1;
	int j = 0;
	char string[30];
	char string2[30];

	while(token[i] != ',')
	{
		string[j] = token[i];
		i++;
		j++;
	}
	if (token[i+1] == ',')
	{
		string[j] = token[i];
		string[j+1] = '\0';
	}
	else
		string[j] = '\0';

	i++;
	j = 0;

	while(token[i] != '>')
	{
		string2[j] = token[i];
		i++;
		j++;
	}
	string2[j] = '\0';
	strcpy(nome_var,string2);


	limpa_buffer(token,100);
	strcpy(token,string);

	//return string;		
}


int verifica_proximo(FILE *arquivo, char *tipo_var_ant, tipo lista_tipos, char* nome_op){

	char *token;
	char *nome_var;
	char *tipo_var;
	fpos_t pos;

    token = (char *) calloc (1,sizeof(char)*NUMCHARS);
	nome_var = (char *) calloc (1,sizeof(char)*30);
	tipo_var = (char *) calloc (1,sizeof(char)*15);

	//Pega posição atual do arquivo
	fgetpos(arquivo,&pos);

	//Pega próximo token
	token = lexico(arquivo);
	limpa_simbolo(token,nome_var);
	//printf("token!!!!!!!!!!!!!!!!!!!1 -> '%s'\n",token);

	//Volta à posição do arquivo	
	fsetpos(arquivo,&pos);

	//Se próximo é um id, procura seu tipo
	if(strcmp(token,"id") == 0)
	{
		if (busca_na_lista(nome_var,lista_tipos,tipo_var))
		{
			//Verifica se tipos são iguais
			if (strcmp(tipo_var_ant,tipo_var) == 0)
				return 1;
		}
		//Se não achar tipo, id não declarada
		else
		{
			printf("Erro semântico: Variável '%s' não declarada!\n", nome_var);
			return 0;
		}
	}
	//Varifica Se inteiro e número
	if (strcmp(nome_op,"/") == 0 && strcmp(nome_var,"0") == 0){
		printf("Erro semântico: Divisão por zero!\n");
		return 1;
	}
	if(strcmp(tipo_var_ant,"int") == 0 && strcmp(token,"Num") == 0)
		return 1;
	//Varifica Se float e número float
	else if(strcmp(tipo_var_ant,"float") == 0 && strcmp(token,"Num_Float") == 0)
		return 1;
	//Varifica Se char e char
	else if(strcmp(tipo_var_ant,"char") == 0 && strcmp(token,"str") == 0)
		return 1;
	else
		return 0;

}


int semantico(char *token, char *token_ant, char *nome_var_ant, tipo lista_tipos, FILE *arquivo)
{

	int k;
	type aux;
	type percorre;
	char *nome_var;
	char *tipo_var;

	nome_var = (char *) calloc (1,sizeof(char)*30);
	tipo_var = (char *) calloc (1,sizeof(char)*30);

	//se encotrou o token FIM do programa, termina.
  if(strcmp(token,"END") == 0)
		return 1;

	//recebe o token e devolve o simbolo limpo
  limpa_simbolo(token,nome_var);

	//declaração de variável - se foi encontrado um id e o mesmo era precedido um por uma declaração como int, float, char
	if ((strcmp(token_ant,"int") == 0) || (strcmp(token_ant,"float") == 0) || (strcmp(token_ant,"char") == 0))
	{
		if (strcmp(token,"id") == 0)
		{
				
			//cria um nó da lista de simbolos e insere a variavel encontrada.				
			aux = (type)calloc(1,sizeof(struct type));
			aux->tipo = (char *) calloc (1,sizeof(char)*100);
			aux->id = (char *) calloc (1,sizeof(char)*100);
			aux->valor = (char *) calloc (1,sizeof(char)*100);
			aux->prox = NULL;

			strcpy(aux->tipo,token_ant);
			strcpy(aux->id,nome_var);

			if (busca_na_lista(nome_var,lista_tipos,tipo_var))
			{
				fprintf(stderr,"Erro semântico: Variável '%s' já foi declarada\n",nome_var);
				strcpy(nome_var_ant,nome_var);				
				return 1;
			}

			//Insere na lista de simbolos, quando no começo.			
			if(lista_tipos->prim == NULL)
			{
				lista_tipos->prim = aux;
			}
			else
			{ //insere na lista de simbolos, quando no meio.
				percorre = lista_tipos->prim;
				while(percorre->prox != NULL)
					percorre = percorre->prox;
				percorre->prox = aux;
			}
			strcpy(nome_var_ant,nome_var);		
			return 2;
		}
	}
	else
	{
		//Se não é declaração, verifica se id já foi declarada
		if (strcmp(token_ant,"id") == 0)
		{
			if(!busca_na_lista(nome_var_ant,lista_tipos,tipo_var))
			{
				printf("Erro semântico: Variável '%s' não declarada!\n", nome_var_ant);
				//return ERRO;
			}

			else
			{	
				if((strcmp(token,"=") == 0) || (strcmp(token,"op_aritm") == 0))
				{
					//próximo tem que ser do mesmo tipo que tipo_var
					if (verifica_proximo(arquivo,tipo_var,lista_tipos,nome_var) == 0)
						printf("Erro semântico: conflito de tipos -> '%s'\n",nome_var_ant);
				}
			}
		}
	}

	strcpy(nome_var_ant,nome_var);
	return 1;
}

int define_se_var_ou_func(char *token, char *token_ant, tipo lista_tipos)
{
	type percorre;
	char *nome_var;
	nome_var = (char *) calloc (1,sizeof(char)*30);
	percorre = lista_tipos->prim;
	while(percorre != NULL){
		if(strcmp(token_ant,percorre->id) == 0)
		{
				limpa_simbolo(token,nome_var);				
				if ((strcmp(token,";") == 0) || (strcmp(token,",") == 0) || (strcmp(token,")") == 0)){
					strcpy(percorre->valor,"variavel");		
				}
				else if (strcmp(token,"(") == 0){
					strcpy(percorre->valor,"funcao");		
				}
				return 1;
		}		
		percorre = percorre->prox;
	}
	return 0;	
}

